﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using PersonaLibrary.Search;
using System.Linq.Expressions;

namespace PersonaLibrary.ViewModel
{
    internal class SearchViewModel<TEntity> : BaseViewModel<View.SearchView.SearchView>
        where TEntity : class
    {
        private RelayCommand _commitCommand;
        private RelayCommand _addNewRowCommand;
        private RelayCommand _removeRowCommand;
        private readonly ObservableCollection<SearchItemModel> _searchedItems = new ObservableCollection<SearchItemModel>();

        public SearchViewModel()
        {
            Parametr = Expression.Parameter(typeof (TEntity));
        }

		protected override void OnViewCreated()
		{
			base.OnViewCreated();
			AddNewRow();
		}

        protected ParameterExpression Parametr { private set; get; }

        public ObservableCollection<SearchItemModel> SearchedItems
        {
            get
            {
                return _searchedItems;
            }
        }

        public RelayCommand CommitCommand
        {
            get
            {
                if (_commitCommand == null)
                {
                    _commitCommand = new RelayCommand(param => Commit(), param => CanCommit());
                }
                return _commitCommand;
            }
        }

        public RelayCommand AddNewRowCommand
        {
            get
            {
                if (_addNewRowCommand == null) _addNewRowCommand = new RelayCommand(param => AddNewRow(), param => true);
                return _addNewRowCommand;
            }
        }

        public RelayCommand RemoveRowCommand
        {
            get
            {
                if (_removeRowCommand == null) _removeRowCommand = new RelayCommand(param => RemoveRow((Search.SearchItemModel)param), param => param is Search.SearchItemModel);
                return _removeRowCommand;
            }
        }

        private void AddNewRow()
        {
			if (SearchedItems.Count == 0)
				SearchedItems.Add(new SearchItemModel { Properties = CreateProeprties(), BinaryEnable = false});
			else
				SearchedItems.Add(new SearchItemModel { Properties = CreateProeprties(), SelectedBinaryOperator = "И"});
        }

        private void RemoveRow(SearchItemModel arg)
        {
            _searchedItems.Remove(arg);
        }

        public virtual void Commit()
        {
            OnExpresseionCreated(ToExpression());
            View.Close();
        }

        public virtual bool CanCommit()
        {
            return true;
        }

        private LambdaExpression ToExpression()
        {
            Expression result = null;
            
            foreach (SearchItemModel item in _searchedItems)
            {
                if (_searchedItems.IndexOf(item) == 0)
                    result = item.SelectedProperty.CreateUnary();
                else
                    result = item.CreateBinary(result, item.SelectedProperty.CreateUnary());
            }

            if (result != null)
            {
                LambdaExpression expression = Expression.Lambda(result, Parametr);
                return expression;
            }
            return null;
        }

        protected virtual List<BaseSearchProperty> CreateProeprties()
        {
            throw new NotImplementedException();
        }

        protected virtual void OnExpresseionCreated(LambdaExpression expression)
        {
            
        }
    }
}
